package tms.unitTests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;

import tms.model.Person;
import tms.model.Project;
import tms.model.Task;

/**
 * ProjectUnitTests class contains the units tests of the methods in the Project class 
 * 
 * @author Rolf Schmidt
 *
 */
public class ProjectUnitTests {

	/**
	 * helper method called before every unit test to clear the project
	 */
	@Before
    public void setUp() {
        Project.getInstance().clear();
    }
	
	/**
	 * test that the only instance of the project is not null 
	 * and that it contains no tasks and people
	 */
	@Test
	public void testProjectGetInstance1() {
		Project project = Project.getInstance();
		assertNotNull(project);
		assertTrue(project.getTaskTree().getTasklist().isEmpty());
		assertTrue(project.getTaskTree().getTaskMap().isEmpty());
		assertTrue(project.getPeopleList().isEmpty());
    }
	
	/**
	 * test that the getInstance() always returns the same instance of the project no matter how
	 * many times it is called
	 */
	@Test
	public void testProjectGetInstance2() {
		Project project1 = Project.getInstance();
		Project project2 = Project.getInstance();
		Project project3 = Project.getInstance();
		
		assertNotNull(project1);
		assertSame(project1, project2);
		assertSame(project2, project3);
    }
	
	/**
	 * test that setting the people list on an empty project returns an empty people list
	 */
	@Test
	public void testProjectSetPeopleList1() {
		Project project = Project.getInstance();

		PrivateAccessor.getPrivateMethod(project, "setPeopleList", null);

		assertTrue(project.getPeopleList().isEmpty());
	}
	
	/**
	 * test that setting the people list on a non-empty project containing three tasks
	 * assigned to two different people
	 * 
	 * expect to see a people list with two entries
	 */
	@Test
	public void testProjectSetPeopleList2() {
		Project project = Project.getInstance();
		
		Task task1 = project.addTask();
		task1.setPerson("Person 1");
		Task task2 = project.addTask();
		task2.setPerson("Person 2");
		Task task3 = project.addTask();
		task3.setPerson("Person 1");

		PrivateAccessor.getPrivateMethod(project, "setPeopleList", null);
		
		assertEquals(2, project.getPeopleList().size());
		Person person1 = project.getPeopleList().get(0);
		Person person2 = project.getPeopleList().get(1);
		
		assertEquals("Person 1", person1.getName());
		assertEquals("Person 2", person2.getName());
		assertEquals(2 * Person.HOURS_IN_WORKING_DAY, person1.getHours());
		assertEquals(1 * Person.HOURS_IN_WORKING_DAY, person2.getHours());
		assertEquals("0, 2", person1.getTasklist());
		assertEquals("1", person2.getTasklist());
	}
	
	/**
	 * test that getting the taskTree from an empty project returns an empty list
	 */
	@Test
	public void testProjectGetTasktree1() {
		Project project = Project.getInstance();

		assertTrue(project.getTaskTree().getTasklist().isEmpty());
		assertTrue(project.getTaskTree().getTaskMap().isEmpty());
	}

	/**
	 * test that getting the taskTree from a non-empty project containing three tasks
	 * returns these tasks
	 */
	@Test
	public void testProjectGetTasktree2() {
		Project project = Project.getInstance();

		Task task1 = project.addTask();
		task1.setTitle("Title 1");
		Task task2 = project.addTask();
		task2.setTitle("Title 2");
		Task task3 = project.addTask();
		task3.setTitle("Title 3");
		
		assertEquals(3, project.getTaskTree().getTasklist().size());
		assertEquals(3, project.getTaskTree().getTaskMap().size());
		
		assertEquals(task1, project.getTaskTree().getTasklist().get(0));
		assertEquals(task2, project.getTaskTree().getTasklist().get(1));
		assertEquals(task3, project.getTaskTree().getTasklist().get(2));
	}
	
	/**
	 * clear an empty Project
	 */
	@Test
	public void testProjectClear1() {
		Project project = Project.getInstance();

		project.clear();
		assertTrue(project.getTaskTree().getTasklist().isEmpty());
		assertTrue(project.getTaskTree().getTaskMap().isEmpty());
		assertTrue(project.getPeopleList().isEmpty());
	}

	/**
	 * clear a non-empty empty Project
	 */
	@Test
	public void testProjectClear2() {
		Project project = Project.getInstance();
		
		project.addTask();
		project.addTask();
		project.addTask();

		assertEquals(3, project.getTasklist().size());

		project.clear();
		assertTrue(project.getTaskTree().getTasklist().isEmpty());
		assertTrue(project.getTaskTree().getTaskMap().isEmpty());
		assertTrue(project.getPeopleList().isEmpty());
	}

}
